package com.sugon.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AuthCheck;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.IgnoreAuth;
import com.sugon.annotation.LoginUser;
import com.sugon.entity.*;
import com.sugon.modules.alarm.service.AlarmCodeBaseService;
import com.sugon.modules.analyse.model.chart.PieChartOptionDataVO;
import com.sugon.modules.analyse.service.IDeviceAnalyseService;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.device.consts.DevRepairTicketStage;
import com.sugon.modules.device.consts.DeviceTicketSource;
import com.sugon.modules.device.consts.enums.DevRepairTicketStatusEnum;
import com.sugon.modules.device.model.vo.DevCallRepairParamVO;
import com.sugon.modules.device.model.vo.DevRepairRecordVO;
import com.sugon.modules.device.model.vo.PerfectDevRepairRecordParamVO;
import com.sugon.modules.device.service.IDeviceRepairManager;
import com.sugon.modules.sys.consts.SysDeptConst;
import com.sugon.modules.sys.model.vo.PickerModel;
import com.sugon.modules.sys.utils.FaultTypeTreeNodeUtils;
import com.sugon.service.*;
import com.sugon.util.ApiBaseAction;
import com.sugon.util.ApiPageUtils;
import com.sugon.utils.Query;
import com.sugon.utils.R;
import com.sugon.utils.ShiroUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 维修工单接口
 *
 * @author YuXD
 * @since 2020-11-22 19:48
 */
@Api(tags = "维修工单接口")
@RestController
@RequestMapping("/api/devmaintenwork")
public class DeviceRepairApiController extends ApiBaseAction {

    @Autowired
    private FaultTypeService faultTypeService;
    @Autowired
    private IDeviceRepairManager deviceRepairManager;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private TicketLiveImageService ticketLiveImageService;
    @Autowired
    private SysOssService sysOssService;
    @Autowired
    private IDeviceAnalyseService deviceAnalyseService;
    @Resource
    private AlarmCategoryService alarmCategoryService;
    @Resource
    private AlarmCodeBaseService alarmCodeBaseService;
    @Resource
    private DevRepairRecordService devRepairRecordService;

    @AutoLog(value = "故障现场照片上传", busModule = BusModule.DEVICE_REPAIR)
    @IgnoreAuth
    @ApiOperation(value = "故障现场照片上传API")
    @ApiImplicitParam(name = "ticketId", value = "维修工单ID", paramType = "query", dataType = "String", required = true)
    @PostMapping("/uploadLiveBarPhoto")
    public ApiResult<String> uploadLiveBarPhoto(@RequestParam String ticketId, @RequestParam("file") MultipartFile file) throws Exception {
        ApiResult<String> apiResult = new ApiResult<>();
        // 校验设备是否存在
        DevRepairRecordEntity ticket = devRepairRecordService.queryObject(ticketId);
        if (ticket == null) {
            return apiResult.failMsg("设备维护工单信息不存在！");
        }
        // 1、上传图片到文件服务器获取存储路径等相关信息
        R uploadResult = sysOssService.upload("device", "repair", file);
        // 2、添加维修工单现场图片记录
        ticketLiveImageService.addRepairTicketLiveImage(ticketId, MapUtil.getStr(uploadResult, "url"));
        return apiResult.succMsg("上传成功");
    }

    @AutoLog(value = "故障报修", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation(value = "生产班组长设备报修")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "devId", value = "设备ID", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "faultId", value = "报警/故障ID", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "faultCode", value = "报警/故障编码", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "faultDesc", value = "报警/故障描述", paramType = "query", dataType = "String")
    })
    @PostMapping("/callRepair")
    public ApiResult<String> callRepair(@ApiIgnore @LoginUser SysUserEntity loginUser, @ApiIgnore @Validated DevCallRepairParamVO callRepairParam, BindingResult bindingResult) {
        // 常规校验
        ApiResult<String> apiResult = getValidApiResult(bindingResult);
        if (apiResult != null) {
            return apiResult;
        }
        apiResult = new ApiResult<>();
        // 校验设备是否存在
        DeviceInfoEntity device = deviceInfoService.queryObject(callRepairParam.getDevId());
        if (device == null) {
            return apiResult.failMsg("设备信息不存在！");
        }
        // 只有本车间人员可以报修本车间的设备
        if (StrUtil.isAllNotEmpty(loginUser.getDeptCode(), device.getDeptCode())) {
            if (!StrUtil.equals(loginUser.getDeptCode(), StrUtil.sub(device.getDeptCode(), 0, 4))) {
                return apiResult.failMsg("非本车间人员不可报修当前设备！");
            }
        }
        // 校验是否存在维修中的工单。如果存在，则无法发起报修
        Map<String, Object> param = MapUtil.newHashMap();
        param.put("devId", callRepairParam.getDevId());
        param.put("delFlag", 1);
        param.put("devStatusList", CollectionUtil.newArrayList(DevRepairTicketStatusEnum.CALL_REPAIR.getValue(), DevRepairTicketStatusEnum.START_REPAIR.getValue()));
        List<DevRepairRecordEntity> ingRepairRecordList = devRepairRecordService.queryList(param);
        if (CollectionUtil.isNotEmpty(ingRepairRecordList)) {
            return apiResult.failMsg("当前设备有未完成工单，无法发起报修！");
        }

        // 构建维修工单基础信息
        DevRepairRecordEntity repairRecord = new DevRepairRecordEntity();

        /*
         faultId faultCode faultDesc 有三种情形：
         1、设备报警库中存在该报警时，faultId必填，faultCode和faultDesc不填
         2、设备报警代码库中不存在，但HMI报修已存在时：faultCode和faultDesc必填，faultId不填
         3、设备报警代码库不存在，HMI报修中也不存在时上传报警代码照片，faultId faultCode faultDesc都不需要填写 只上传照片即可
         */
        if (StrUtil.isAllEmpty(callRepairParam.getFaultId(), callRepairParam.getFaultCode(), callRepairParam.getFaultDesc()) && CollectionUtil.isEmpty(callRepairParam.getFaultImages())) {
            return apiResult.failMsg("报警相关信息必填！");
        } else {
            if (StrUtil.isNotEmpty(callRepairParam.getFaultId())) {
                // 校验设备报警是否存在
                AlarmCodeBaseEntity alarmCodeBase = alarmCodeBaseService.queryObject(callRepairParam.getFaultId());
                if (alarmCodeBase == null) {
                    return apiResult.failMsg("设备报警不存在，请确认！");
                }
                // 是否是这个设备的
                if (!callRepairParam.getDevId().equals(alarmCodeBase.getDevId())) {
                    return apiResult.failMsg("只可以从该设备的报警代码库中选择报警！");
                }
                repairRecord.setFaultCategoryId(alarmCodeBase.getAlarmCategoryId());
                repairRecord.setFaultId(alarmCodeBase.getId());
                repairRecord.setFaultCode(alarmCodeBase.getAlarmCode());
                repairRecord.setFaultDesc(alarmCodeBase.getAlarmDesc());
                repairRecord.setUploadDesc(alarmCodeBase.getAlarmDesc());
            } else if (StrUtil.isAllNotEmpty(callRepairParam.getFaultCode(), callRepairParam.getFaultDesc())) {
                repairRecord.setFaultCode(callRepairParam.getFaultCode());
                repairRecord.setFaultDesc(callRepairParam.getFaultDesc());
                repairRecord.setUploadDesc(callRepairParam.getFaultDesc());
            }
            repairRecord.setFaultImages(callRepairParam.getFaultImages());
        }
        repairRecord.setUploadDesc(callRepairParam.getFaultDesc());
        repairRecord.setDevId(device.getId());
        repairRecord.setWorkshopId(device.getDevFarm());
        repairRecord.setUploadId(loginUser.getUserId());
        repairRecord.setUploadDate(DateUtil.date());
        repairRecord.setCreateBy(loginUser.getUserId());
        return deviceRepairManager.callRepair(repairRecord) ? apiResult.success("报修成功！") : apiResult.failMsg("报修失败，请稍后重试");
    }

    @AuthCheck
    @ApiOperation(value = "获取设备维修工单统计报表API")
    @ApiImplicitParam(name = "statType", value = "统计类别，本周还是本月", paramType = "query", dataType = "string", required = true, allowableValues = "WEEKLY,MONTHLY")
    @PostMapping("/stat")
    public ApiResult<PieChartOptionDataVO> loadDevRepairTicketStat(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String statType) {
        ApiResult<PieChartOptionDataVO> apiResult = new ApiResult<>();
        // 校验是否合法的统计类别
        if (!StrUtil.equalsAny(statType, "WEEKLY", "MONTHLY")) {
            return apiResult.failMsg("非法统计类别！");
        }
        // 车间看车间，制造处看整体
        String workShopId = loginUser.getWorkShopId();
        if (SysDeptConst.ZZC_CODE.equals(workShopId)) {
            workShopId = null;
        }
        return apiResult.success(deviceAnalyseService.loadDevRepairTicketStat(statType, workShopId));
    }

    @AutoLog(value = "移动端查看维修工单列表", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation(value = "获取设备维修工单列表API", notes = "返回未完成状态的工单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "limit", value = "每页记录数", paramType = "query", dataType = "Integer", required = true)
    })
    @PostMapping("getDevMaintenWorkList")
    public ApiResult<ApiPageUtils> getDevMaintenWorkList(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam Map<String, Object> params) {
        ApiResult<ApiPageUtils> apiResult = new ApiResult<>();
        params.put("sidx", "UPLOAD_DATE");
        params.put("order", "DESC");

        // 1、所有人员看默认返回本日的所有工单+历史未关闭的，不管哪个车间
        params.put("isMobile", 1);
        // 移动端只查看未删除的
        params.put("delFlag", 1);
        params.put("today", DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN));

        // 2、各车间人员看自己车间的，设备工程处看所有的
        String filterSql = "";
        if (StrUtil.isNotEmpty(loginUser.getWorkShopId()) && !StrUtil.equals(loginUser.getWorkShopId(), SysDeptConst.ZZC_CODE)) {
            filterSql += " AND WORKSHOP_ID = '" + loginUser.getWorkShopId() + "'";
        }
        params.put("filterSql", filterSql);

        // 处理下查询日期
        String queryDate = MapUtil.getStr(params, "queryDate");
        if (StrUtil.isNotEmpty(queryDate)) {
            params.put("beginTime", queryDate + " 0:00:00");
            params.put("endTime", queryDate + " 23:59:59");
            params.remove("queryDate");
        }

        //查询列表数据
        Query map = new Query(params);
        List<DevRepairRecordEntity> devMaintenWorkList = devRepairRecordService.queryList(map);
        int total = devRepairRecordService.queryTotal(map);
        ApiPageUtils pageUtil = new ApiPageUtils(devMaintenWorkList, total, map.getLimit(), map.getPage());
        return apiResult.success(pageUtil);
    }

    /**
     * 维修工单查询详情接口D
     *
     * @param id
     * @return
     */
    @AutoLog(value = "移动端查看工单详情", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation(value = "维修工单查询详情接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", paramType = "query", dataType = "String", required = true)
    })
    @RequestMapping(value = "getDetailById", method = RequestMethod.POST)
    public ApiResult<DevRepairRecordEntity> getDetailById(@RequestParam String id) {
        ApiResult<DevRepairRecordEntity> apiResult = new ApiResult<>();
        // 获取维修记录
        DevRepairRecordEntity repairRecord = devRepairRecordService.queryObject(id);
        if (repairRecord == null) {
            return apiResult.failMsg("维修记录不存在，请确认！");
        }
        // 设置下现场照片
        repairRecord.setFaultImages(ticketLiveImageService.getTicketLiveImages("维修前", repairRecord.getId(), "REPAIR"));
        return apiResult.success(repairRecord);
    }

    @AutoLog(value = "移动端查看维修记录详情", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation(value = "根据维修工单ID查询设备维修记录API")
    @ApiImplicitParam(name = "id", value = "设备维修工单ID", paramType = "query", dataType = "String", required = true)
    @RequestMapping(value = "queryRepairRecordByTicketId", method = RequestMethod.POST)
    public ApiResult<DevRepairRecordEntity> queryRepairRecordByTicketId(@RequestParam String ticketId) {
        ApiResult<DevRepairRecordEntity> apiResult = new ApiResult<>();
        // 校验维修记录是否存在
        DevRepairRecordEntity repairRecord = devRepairRecordService.queryObject(ticketId);
        if (repairRecord == null) {
            return apiResult.failMsg("设备维修记录不存在，请确认！");
        }
        // 设置设备报警分类：大类、种类、小类的ID
        if (StrUtil.isNotEmpty(repairRecord.getFaultCategoryId())) {
            List<String> alarmCatetoryIdList = alarmCategoryService.listBMS(repairRecord.getFaultCategoryId());
            if (CollectionUtil.isNotEmpty(alarmCatetoryIdList)) {
                for (int i = 0; i < alarmCatetoryIdList.size(); i++) {
                    if (i == 0) {
                        repairRecord.setVrtId(alarmCatetoryIdList.get(i));
                    } else if (i == 1) {
                        repairRecord.setVfgId(alarmCatetoryIdList.get(i));
                    } else if (i == 2) {
                        repairRecord.setFaultCategoryId(alarmCatetoryIdList.get(i));
                    }
                }
            }
        }
        return apiResult.success(repairRecord);
    }

    @AutoLog(value = "移动端查看设备维修记录列表", busModule = BusModule.DEVICE_REPAIR)
    @ApiOperation(value = "获取设备维修记录API")
    @ApiImplicitParam(name = "devId", value = "devId", paramType = "query", dataType = "String", required = true)
    @RequestMapping(value = "loadRepairRecordList", method = RequestMethod.POST)
    public ApiResult<List<DevRepairRecordVO>> loadRepairRecordList(@RequestParam("devId") String devId) {
        ApiResult<List<DevRepairRecordVO>> apiResult = new ApiResult<>();
        return apiResult.success(deviceRepairManager.loadDevRepairRecord(devId));
    }

    @AutoLog(value = "移动端开始维修", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation("维修工确认开始维修")
    @ApiImplicitParam(name = "id", value = "维修工单ID", paramType = "query", dataType = "String", required = true)
    @RequestMapping("/startRepair")
    public ApiResult<String> startRepair(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String id) {
        ApiResult<String> apiResult = new ApiResult<>();
        // 校验工单是否存在
        DevRepairRecordEntity repairRecord = devRepairRecordService.queryObject(id);
        if (repairRecord == null) {
            return apiResult.failMsg("工单信息不存在，请确认！");
        }
        // 校验是否处于 待开始状态
        Integer ticketStatus = repairRecord.getDevStatus();
        if (!DevRepairTicketStage.CALL_REPAIR.equals(ticketStatus)) {
            return apiResult.failMsg("只可以确认维修处于[待维修]状态的工单！");
        }
        repairRecord.setRepairUser(loginUser.getUserId());
        return deviceRepairManager.confirmRepair(repairRecord) ? apiResult.success() : apiResult.fail();
    }

    @ApiOperation("生产班长催单")
    @RequestMapping("/urgeSave")
    @ResponseBody
    public ApiResult<String> urgeSave(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String id) {
        ApiResult<String> apiResult = new ApiResult<>();
        DevRepairRecordEntity work = devRepairRecordService.queryObject(id);
        if (work == null) {
            return apiResult.failMsg("无效工单");
        }
        return deviceRepairManager.urge(id, loginUser.getUserId()) ? apiResult.success() : apiResult.fail();
    }

    @AutoLog(value = "移动端完成维修", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation("维修工完成维修API")
    @ApiImplicitParam(name = "id", value = "维修工单ID", paramType = "query", dataType = "String", required = true)
    @RequestMapping("/completeRepair")
    public ApiResult<String> completeRepair(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String id) {
        ApiResult<String> apiResult = new ApiResult<>();
        DevRepairRecordEntity repairTicket = devRepairRecordService.queryObject(id);
        if (repairTicket == null) {
            return apiResult.failMsg("无效工单");
        }
        // 如果没有结束维修时间，那么设置为当前系统时间
        Date endRepairTime = repairTicket.getRepairEndDate();
        if (endRepairTime == null) {
            endRepairTime = DateUtil.date();
            repairTicket.setRepairEndDate(endRepairTime);
        }
        // 结束维修时，维修时长不得小于5分钟
        if (DateUtil.between(repairTicket.getRepairStartDate(), endRepairTime, DateUnit.MINUTE) < 5) {
            return apiResult.failMsg("维修时长不得小于5分钟！");
        }
        repairTicket.setUpdateBy(loginUser.getNickName());
        return deviceRepairManager.completeRepair(repairTicket) ? apiResult.success() : apiResult.fail();
    }

    @AutoLog(value = "移动端完善维修记录", busModule = BusModule.DEVICE_REPAIR)
    @AuthCheck
    @ApiOperation(value = "完善维修记录API")
    @RequestMapping("/addRepairRecord")
    public ApiResult<String> addRepairRecord(@Validated @RequestBody PerfectDevRepairRecordParamVO repairRecordParam, BindingResult bindingResult) {
        ApiResult<String> apiResult = new ApiResult<>();
        // 维修记录ID必填
        String repairRecordId = repairRecordParam.getId();
        if (StrUtil.isEmpty(repairRecordId)) {
            return apiResult.failMsg("维修记录ID必填！");
        }
        // 校验维修记录是否存在
        DevRepairRecordEntity repairRecordInDB = devRepairRecordService.queryObject(repairRecordId);
        if (repairRecordInDB == null) {
            return apiResult.failMsg("维修记录不存在，请确认！");
        }
        // 如果有报修时间，那么开始维修和结束维修都不得早于报修时间
        Date repairStartDate = repairRecordParam.getRepairStartDate();
        Date repairEndDate = repairRecordParam.getRepairEndDate();
        Date uploadDate = repairRecordInDB.getUploadDate();
        if (uploadDate != null) {
            if (repairStartDate != null && repairStartDate.before(uploadDate)) {
                return apiResult.failMsg("维修开始时间不得早于报修时间！");
            }
            if (repairEndDate != null && repairEndDate.before(uploadDate)) {
                return apiResult.failMsg("维修结束时间不得早于报修时间！");
            }
        }

        // 维修时长必须大于5分钟
        if (DateUtil.between(repairRecordParam.getRepairStartDate(), repairRecordParam.getRepairEndDate(), DateUnit.MINUTE) < 5) {
            return apiResult.failMsg("维修时长不得小于5分钟！");
        }

        // 校验设备是否存在
        DeviceInfoEntity device = deviceInfoService.queryObject(repairRecordParam.getDevId());
        if (device == null) {
            return apiResult.failMsg("设备不存在，请确认！");
        }

         /*
            报警分类CCC一级的ID(faultCategoryId)    设备报警库ID(faultId)
         */
        if (StrUtil.isAllEmpty(repairRecordParam.getFaultCategoryId(), repairRecordParam.getFaultId())) {
            return apiResult.failMsg("CCC分类和设备报警库两者必须指定其中之一！");
        }

         /*
            1、开始维修时间和开始结束时间不得早于当前系统时间
            2、开始维修时间不能晚于结束维修时间
         */
        DateTime current = DateUtil.date();
        if (repairRecordParam.getRepairStartDate().after(current)) {
            return apiResult.failMsg("维修开始时间不得晚于当前系统时间！");
        }
        if (repairRecordParam.getRepairEndDate().after(current)) {
            return apiResult.failMsg("维修结束时间不得晚于当前系统时间！");
        }
        if (repairRecordParam.getRepairStartDate().after(repairRecordParam.getRepairEndDate())) {
            return apiResult.failMsg("维修开始时间不得晚于维修结束时间！");
        }
        // 维修时长必须大于5分钟
        if (DateUtil.between(repairRecordParam.getRepairStartDate(), repairRecordParam.getRepairEndDate(), DateUnit.MINUTE) < 5) {
            return apiResult.failMsg("维修时长不得小于5分钟！");
        }

        // 校验如果填写故障预防措施的话，必填校验和日期先后校验
        List<DevFaultPreventMeasure> measureList = repairRecordParam.getPreventMeasureList();
        if (CollectionUtil.isNotEmpty(measureList)) {
            for (DevFaultPreventMeasure measure : measureList) {
                if (!ObjectUtil.isAllNotEmpty(measure.getContent(), measure.getStartDate(), measure.getEndDate())) {
                    return apiResult.failMsg("制定措施时，措施内容、开始时间和结束时间必填！");
                }
                // 开始维修时间不能晚于结束维修时间
                if (measure.getStartDate().after(measure.getEndDate())) {
                    return apiResult.failMsg("预防措施开始时间不得晚于结束时间！");
                }
            }
            repairRecordInDB.setPreventMeasureList(measureList);
        }

        /*
            如果设备报警库ID没填，说明是新增的
                校验下指定设备，特定的报警分类下是否存在这个报警代码
                    如果存在，则直接提示已存在
                    如果不存在，则创建并返回
            如果填写了，需要跟报警代码和
         */
        AlarmCodeBaseEntity alarmCodeBase;
        String faultId = repairRecordParam.getFaultId();
        if (StrUtil.isNotEmpty(faultId)) {
            alarmCodeBase = alarmCodeBaseService.queryObject(faultId);
            if (alarmCodeBase == null) {
                return apiResult.failMsg("当前设备报警代码库不存在，请确认！");
            }
            // 校验是否是这个设备的
            if (!repairRecordParam.getDevId().equals(alarmCodeBase.getDevId())) {
                return apiResult.failMsg("当前设备报警不是这个设备的，请确认！");
            }
            // 验证下报警分类&报警代码的关系
            if (StrUtil.isEmpty(repairRecordParam.getFaultCategoryId())) {
                repairRecordParam.setFaultCategoryId(alarmCodeBase.getAlarmCategoryId());
            } else {
                // 校验是否是这个报警分类下的
                if (!repairRecordParam.getFaultCategoryId().equals(alarmCodeBase.getAlarmCategoryId())) {
                    return apiResult.failMsg("当前设备报警不属于这个报警分类，请确认！");
                }
            }
            repairRecordParam.setFaultCode(alarmCodeBase.getAlarmCode());
            repairRecordParam.setFaultDesc(alarmCodeBase.getAlarmDesc());
        } else {
            // 必填校验
            if (StrUtil.isEmpty(repairRecordParam.getFaultCode())) {
                return apiResult.failMsg("报警代码必填！");
            }
             /*
                理论上：一台设备不管分为多少个部位，报警代码是唯一的
                手动新增时需要区分报警代码已存在和不存在的情形：
                9999：不存在，通用代码
                9999之外的其他情形：
             */
            if (!"9999".equals(repairRecordParam.getFaultCode())) {
                // 获取匹配的设备报警库。如果不存在，则创建
                alarmCodeBase = alarmCodeBaseService.query(null, repairRecordParam.getDevId(), repairRecordParam.getFaultCode());
                if (alarmCodeBase != null) {
                    return apiResult.failMsg(StrUtil.format("当前设备报警代码[{}]已关联报警分类：[{}]，无需重复录入！", repairRecordParam.getFaultCode(), alarmCodeBase.getTreeName()));
                }
            }
            alarmCodeBase = alarmCodeBaseService.queryOrCreateIfNotExists(repairRecordParam.getFaultCategoryId(), repairRecordParam.getDevId(), repairRecordParam.getFaultCode(), repairRecordParam.getFaultDesc(), true);
        }
        // 手机端默认不允许修改开始时间和结束时间
        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreProperties("measureList", "maintenRecordId", "repairStartDate", "repairEndDate");
        // 只允许补充录入的维修记录可以修改开始时间和结束时间
        if (!StrUtil.equals(DeviceTicketSource.SECOND.name(), repairRecordInDB.getSource())) {
            copyOptions.setIgnoreProperties("measureList", "maintenRecordId", "repairStartDate", "repairEndDate");
        }
        BeanUtil.copyProperties(repairRecordParam, repairRecordInDB, copyOptions);
        repairRecordInDB.setFaultId(alarmCodeBase.getId());
        repairRecordInDB.setFaultCategoryId(repairRecordParam.getFaultCategoryId());
        // 设置故障时间
        repairRecordInDB.setFaultDuration(DateUtil.between(repairRecordInDB.getRepairStartDate(), repairRecordInDB.getRepairEndDate(), DateUnit.MINUTE));
        // 如果维修人员为空，那么默认当前完善维修记录的就是维修人员
        if (StrUtil.isEmpty(repairRecordInDB.getRepairUser())) {
            repairRecordInDB.setRepairUser(ShiroUtils.getUserId());
        }
        repairRecordInDB.setWorkshopId(device.getDevFarm());
        return deviceRepairManager.perfectRepairRecord(repairRecordInDB) ? apiResult.success() : apiResult.fail();
    }

    @ApiOperation("获取设备故障类别APi")
    @RequestMapping("/getFaultTypes")
    public ApiResult<List<PickerModel>> getFaultTypes() {
        ApiResult<List<PickerModel>> result = new ApiResult<>();
        List<PickerModel> faultTypeList = new ArrayList<>();
        List<FaultTypeEntity> faultTypes = faultTypeService.queryList(null);
        // 整合数据到一起
        for (FaultTypeEntity faultType : faultTypes) {
            faultTypeList.add(new PickerModel(faultType));
        }
        // 构建设备组织树
        FaultTypeTreeNodeUtils treeNodeUtils = new FaultTypeTreeNodeUtils(faultTypeList);
        PickerModel root = treeNodeUtils.generateTree("70");
        return result.success(root.getChildren());
    }

}




